From 7ed06480cf46768a42462363ac33b6bb8b8a3cdf Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 10 Nov 2020 14:19:32 +0000 Subject: [PATCH] a11y: Add private API to clone a GtkATContext Some widgets might want to override GtkAccessible and create their own context in order to control the accessible role post-construction time. To avoid explicitly copying the existing state over from the original ATContext to the new one, we need a way to clone the context's state from inside the ATContext itself. --- gtk/gtkatcontext.c | 55 +++++++++++++++++++++++++++++++++++++++ gtk/gtkatcontextprivate.h | 5 ++++ 2 files changed, 60 insertions(+) diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index afdf478067..661ac848b1 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -538,6 +538,61 @@ gtk_at_context_create (GtkAccessibleRole accessible_role, return res; } +/*< private > + * gtk_at_context_clone: (constructor) + * @self: the #GtkATContext to clone + * @role: the accessible role of the clone, or %GTK_ACCESSIBLE_ROLE_NONE to + * use the same accessible role of @self + * @accessible: (nullable): the accessible creating the context, or %NULL to + * use the same #GtkAccessible of @self + * @display: (nullable): the display connection, or %NULL to use the same + * #GdkDisplay of @self + * + * Clones the state of the given #GtkATContext, using @role, @accessible, + * and @display. + * + * If @self is realized, the returned #GtkATContext will also be realized. + * + * Returns: (transfer full): the newly created #GtkATContext + */ +GtkATContext * +gtk_at_context_clone (GtkATContext *self, + GtkAccessibleRole role, + GtkAccessible *accessible, + GdkDisplay *display) +{ + g_return_val_if_fail (self == NULL || GTK_IS_AT_CONTEXT (self), NULL); + g_return_val_if_fail (accessible == NULL || GTK_IS_ACCESSIBLE (accessible), NULL); + g_return_val_if_fail (display == NULL || GDK_IS_DISPLAY (display), NULL); + + if (self != NULL && role == GTK_ACCESSIBLE_ROLE_NONE) + role = self->accessible_role; + + if (self != NULL && accessible == NULL) + accessible = self->accessible; + + if (self != NULL && display == NULL) + display = self->display; + + GtkATContext *res = gtk_at_context_create (role, accessible, display); + + if (self != NULL) + { + g_clear_pointer (&res->states, gtk_accessible_attribute_set_unref); + g_clear_pointer (&res->properties, gtk_accessible_attribute_set_unref); + g_clear_pointer (&res->relations, gtk_accessible_attribute_set_unref); + + res->states = gtk_accessible_attribute_set_ref (self->states); + res->properties = gtk_accessible_attribute_set_ref (self->properties); + res->relations = gtk_accessible_attribute_set_ref (self->relations); + + if (self->realized) + gtk_at_context_realize (res); + } + + return res; +} + gboolean gtk_at_context_is_realized (GtkATContext *self) { diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h index 9f161e9f20..f1b62f8cb8 100644 --- a/gtk/gtkatcontextprivate.h +++ b/gtk/gtkatcontextprivate.h @@ -145,6 +145,11 @@ struct _GtkATContextClass void (* unrealize) (GtkATContext *self); }; +GtkATContext * gtk_at_context_clone (GtkATContext *self, + GtkAccessibleRole role, + GtkAccessible *accessible, + GdkDisplay *display); + GdkDisplay * gtk_at_context_get_display (GtkATContext *self); void gtk_at_context_realize (GtkATContext *self); -- 2.30.2